import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;

import javax.crypto.SecretKey;
import java.util.HashMap;
import java.util.Map;

/**
 * <dependency>
 * <groupId>cn.hutool</groupId>
 * <artifactId>hutool-all</artifactId>
 * <version>5.8.22</version>
 * </dependency>
 * <dependency>
 * <groupId>org.bouncycastle</groupId>
 * <artifactId>bcprov-jdk15to18</artifactId>
 * <version>1.69</version>
 * </dependency>
 * 公私钥加密 国产RSA
 */
public class SmTool {
    public static void main(String[] args) {
        Map<String, String> sm2Keys = sm2Keys();
        String sy = sm2Keys.get("sy");
        String gy = sm2Keys.get("gy");
        //生产签名
        String sign = sm2Sign(sy, "dskmdskmk");
        //签名校验
        boolean verify = sm2Verify(gy, "dskmdskmk", sign);
        System.out.println(verify);
        //公钥加密
        String encrypted = sm2EncBase64(sy, gy, "sdasdasd");
        String decrypted = sm2DecBase64(sy, gy, encrypted);
        System.out.println(decrypted);
        //sm3
        System.out.println(sm3("asdas"));
        //sm4
        String sm4Key = sm4Key();
        String s = sm4Enc("asdsad", sm4Key);
        System.out.println(sm4Dec(s, sm4Key));
    }

    public static String sm4Key() {
        SM4 sm4 = SmUtil.sm4();
        SecretKey secretKey = sm4.getSecretKey();
        byte[] encoded = secretKey.getEncoded();
        return HexUtil.encodeHexStr(encoded);
    }

    public static String sm4Enc(String content, String sm4Key) {
        SM4 sm4 = new SM4(HexUtil.decodeHex(sm4Key));
        return sm4.encryptHex(content);
    }

    public static String sm4Dec(String content, String sm4Key) {
        SM4 sm4 = new SM4(HexUtil.decodeHex(sm4Key));
        return sm4.decryptStr(content);
    }


    static String sm3(String str) {
        return SmUtil.sm3(str);
    }

    //生成SM2公私钥
    public static Map<String, String> sm2Keys() {
        SM2 sm2 = new SM2();
        ECPublicKey publicKey = (ECPublicKey) sm2.getPublicKey();
        ECPrivateKey privateKey = (ECPrivateKey) sm2.getPrivateKey();
        // 获取公钥
        byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
        String publicKeyHex = HexUtil.encodeHexStr(publicKeyBytes);

        // 获取64位私钥
        String privateKeyHex = privateKey.getD().toString(16);
        // BigInteger转成16进制时，不一定长度为64，如果私钥长度小于64，则在前方补0
        StringBuilder privateKey64 = new StringBuilder(privateKeyHex);
        while (privateKey64.length() < 64) {
            privateKey64.insert(0, "0");
        }

        Map<String, String> result = new HashMap<>();
        result.put("gy", publicKeyHex);
        result.put("sy", privateKey64.toString());
        return result;
    }

    public static String sm2Sign(String privateKey, String content) {
        SM2 sm2 = new SM2(privateKey, null);
        return sm2.signHex(HexUtil.encodeHexStr(content));
    }

    public static boolean sm2Verify(String publicKey, String content, String sign) {
        SM2 sm2 = new SM2(null, publicKey);
        return sm2.verifyHex(HexUtil.encodeHexStr(content), sign);
    }


    public static String sm2EncBase64(String privateKey, String publicKey, String content) {
        SM2 sm2 = new SM2(privateKey, publicKey);
        return sm2.encryptBase64(content, KeyType.PublicKey);
    }

    public static String sm2DecBase64(String privateKey, String publicKey, String encryptStr) {
        SM2 sm2 = new SM2(privateKey, publicKey);
        return StrUtil.utf8Str(sm2.decrypt(encryptStr, KeyType.PrivateKey));
    }
}
